/*
 * Copyright (c) 2013 Hai Bison
 *
 * See the file LICENSE at the root directory of this project for copying
 * permission.
 */

package com.haibison.android.logs.providers.log;

import static android.provider.BaseColumns._COUNT;
import static android.provider.BaseColumns._ID;
import static com.haibison.android.logs.providers.BaseCols._DATE_CREATED;
import static com.haibison.android.logs.providers.BaseCols._DATE_MODIFIED;
import static com.haibison.android.logs.providers.log.LogContract.DEFAULT_SORT_ORDER;
import static com.haibison.android.logs.providers.log.LogContract.TABLE_NAME;
import static com.haibison.android.logs.providers.log.LogContract.URI_CONTENT;
import static com.haibison.android.logs.providers.log.LogContract.URI_CONTENT_ITEM;

import java.util.Arrays;
import java.util.Date;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.MatrixCursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;

import com.haibison.android.logs.providers.DbUtils;

/**
 * Content provider for logs.
 * 
 * @author Hai Bison
 * @since v1.0 beta
 */
public class LogProvider extends ContentProvider {

    private final UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    private LogHelper mDbHelper;

    @Override
    public boolean onCreate() {
        mUriMatcher.addURI(LogContract.getAuthority(getContext()), null,
                URI_CONTENT);
        mUriMatcher.addURI(LogContract.getAuthority(getContext()), "#",
                URI_CONTENT_ITEM);

        mDbHelper = new LogHelper(getContext());
        return true;
    }// onCreate()

    @Override
    public synchronized int delete(Uri uri, String selection,
            String[] selectionArgs) {
        /*
         * Opens the database object in "write" mode.
         */
        SQLiteDatabase db = mDbHelper.getWritableDatabase();
        String finalWhere;
        int count = 0;

        switch (mUriMatcher.match(uri)) {
        case URI_CONTENT: {
            count = db.delete(TABLE_NAME, selection, selectionArgs);
            break;
        }// URI_CONTENT
        case URI_CONTENT_ITEM: {
            finalWhere = _ID + " = " + uri.getLastPathSegment();
            if (selection != null)
                finalWhere = finalWhere + " AND " + selection;
            count = db.delete(TABLE_NAME, finalWhere, selectionArgs);
            break;
        }// URI_CONTENT_ITEM
        }

        if (count > 0 || selection == null)
            getContext().getContentResolver().notifyChange(uri, null);

        return count;
    }// delete()

    @Override
    public String getType(Uri uri) {
        switch (mUriMatcher.match(uri)) {
        case URI_CONTENT:
            return LogContract.CONTENT_TYPE;
        case URI_CONTENT_ITEM:
            return LogContract.CONTENT_ITEM_TYPE;
        }

        return null;
    }// getType()

    @Override
    public synchronized Uri insert(Uri uri, ContentValues values) {
        if (mUriMatcher.match(uri) != URI_CONTENT)
            return null;

        /*
         * Gets the current time in milliseconds
         */
        final long now = new Date().getTime();
        /*
         * If the values map doesn't contain the creation date/ modification
         * date, sets the value to the current time.
         */
        for (String col : new String[] { _DATE_CREATED, _DATE_MODIFIED })
            if (!values.containsKey(col))
                values.put(col, DbUtils.formatNumber(now, false));

        /*
         * Opens the database object in "write" mode.
         */
        SQLiteDatabase db = mDbHelper.getWritableDatabase();

        /*
         * Performs the insert and returns the ID of the new note.
         */
        long rowId = db.insert(TABLE_NAME, null, values);

        /*
         * If the insert succeeded, the row ID exists.
         */
        if (rowId >= 0) {
            /*
             * Creates a URI with the note ID pattern and the new row ID
             * appended to it.
             */
            Uri noteUri = ContentUris.withAppendedId(
                    LogContract.genContentIdUriBase(getContext()), rowId);

            /*
             * Notifies observers registered against this provider that the data
             * changed.
             */
            getContext().getContentResolver().notifyChange(noteUri, null);
            return noteUri;
        }// if

        return null;
    }// insert()

    @Override
    public synchronized Cursor query(Uri uri, String[] projection,
            String selection, String[] selectionArgs, String sortOrder) {
        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
        qb.setTables(TABLE_NAME);

        SQLiteDatabase db = null;
        Cursor cursor = null;

        /*
         * Choose the projection and adjust the "where" clause based on URI
         * pattern-matching.
         */
        switch (mUriMatcher.match(uri)) {
        case URI_CONTENT: {
            if (Arrays.equals(projection, new String[] { _COUNT })) {
                db = mDbHelper.getReadableDatabase();
                cursor = DbUtils.newCountCursor();
                ((MatrixCursor) cursor).addRow(new Object[] { DatabaseUtils
                        .queryNumEntries(db, TABLE_NAME) });
            }

            break;
        }// URI_CONTENT

        case URI_CONTENT_ITEM: {
            qb.appendWhere(_ID + " = " + uri.getLastPathSegment());
            break;
        }// URI_CONTENT_ITEM
        }

        if (TextUtils.isEmpty(sortOrder))
            sortOrder = DEFAULT_SORT_ORDER;

        if (db == null) {
            db = mDbHelper.getReadableDatabase();
            cursor = qb.query(db, projection, selection, selectionArgs, null,
                    null, sortOrder);
        }

        if (cursor != null)
            cursor.setNotificationUri(getContext().getContentResolver(), uri);

        return cursor;
    }// query()

    @Override
    public synchronized int update(Uri uri, ContentValues values,
            String selection, String[] selectionArgs) {
        SQLiteDatabase db = mDbHelper.getWritableDatabase();
        int count = 0;
        String finalWhere;

        values.put(_DATE_MODIFIED,
                DbUtils.formatNumber(new Date().getTime(), false));

        switch (mUriMatcher.match(uri)) {
        case URI_CONTENT: {
            count = db.update(TABLE_NAME, values, selection, selectionArgs);
            break;
        }// URI_CONTENT

        case URI_CONTENT_ITEM: {
            finalWhere = _ID + " = " + uri.getLastPathSegment();

            if (selection != null)
                finalWhere = finalWhere + " AND " + selection;

            count = db.update(TABLE_NAME, values, finalWhere, selectionArgs);
            break;
        }// URI_CONTENT_ITEM
        }

        if (count > 0)
            getContext().getContentResolver().notifyChange(uri, null);

        return count;
    }// update()

}
